package com.showsu.editor.controller.biz;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson2.JSON;
import com.showsu.editor.asyncService.ICheckAwemeIncludedAsyncService;
import com.showsu.editor.config.SpringContextUtil;
import com.showsu.editor.controller.BaseController;
import com.showsu.editor.entity.bo.XhsAwemeBusinessV2;
import com.showsu.editor.entity.bo.XhsAwemeLinkBaseInfo;
import com.showsu.editor.entity.dto.*;
import com.showsu.editor.entity.po.TblUser;
import com.showsu.editor.entity.po.TblUserExppackage;
import com.showsu.editor.entity.po.TblXhsAwemeDetailRecord;
import com.showsu.editor.entity.po.TblXhsCheckAwemeIncludedRecord;
import com.showsu.editor.entity.vo.*;
import com.showsu.editor.entity.vo.response.*;
import com.showsu.editor.enums.*;
import com.showsu.editor.manage.DouYinBusinessManager;
import com.showsu.editor.manage.WeiboBusinessManager;
import com.showsu.editor.manage.XhsBusinessManager;
import com.showsu.editor.manage.XhsEditorAwemeBusinessManager;
import com.showsu.editor.service.IUserExppackageService;
import com.showsu.editor.service.IXhsAwemeDetailRecordService;
import com.showsu.editor.service.IXhsCheckAwemeIncludedRecordService;
import com.showsu.editor.service.IXhsDewaterRecordService;
import com.showsu.editor.utils.BsResult;
import com.showsu.editor.utils.Constant;
import com.showsu.editor.utils.DateUtil;
import com.showsu.editor.utils.StringUtil;
import com.showsu.editor.utils.aliyun.OssUtil;
import com.showsu.editor.utils.remote.ShuXiuUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: William
 * @Description:
 * @Date: Created in 1:51 下午 2024/9/14
 * @Modified By:
 */
@RestController
@Slf4j
@Api(value = "XhsBusinessController", tags = "xhs业务")
@RequestMapping("/api/xhs")
public class XhsBusinessController extends BaseController {

    @Autowired
    private XhsBusinessManager xhsBusinessManager;

    @Autowired
    private IXhsDewaterRecordService xhsDewaterRecordService;

    @Autowired
    private IXhsAwemeDetailRecordService xhsAwemeDetailRecordService;

    @Autowired
    private IXhsCheckAwemeIncludedRecordService xhsCheckAwemeIncludedRecordService;

    @Autowired
    private ICheckAwemeIncludedAsyncService checkAwemeIncludedAsyncService;

    @Autowired
    private DouYinBusinessManager douYinBusinessManager;

    @Autowired
    private WeiboBusinessManager weiboBusinessManager;

    @Autowired
    private OssUtil ossUtil;

    @Autowired
    private IUserExppackageService userExppackageService;

    @Autowired
    private ShuXiuUtils shuXiuUtils;

    @Autowired
    private XhsEditorAwemeBusinessManager editorAwemeBusinessManager;

    @PostMapping("/dewater/live")
    @ApiOperation(value = "小红书/抖音-live-去水印", notes = "小红书/抖音-live-去水印")
    @ResponseBody
    public BsResult liveParse(@RequestBody XhsDewaterDTO xhsDewaterDTO) {
        if (StringUtils.isBlank(xhsDewaterDTO.getSource()) || !xhsDewaterDTO.getSource().contains("http")) {
            return BsResult.error(ResultCode.RESOURCE_NOT_VALID);
        }
        if (!Constant.checkeXhsDewaterSourceAccordWhiteUrl(xhsDewaterDTO.getSource())) {
            return BsResult.error(ResultCode.RESOURCE_NOT_VALID.getCode(), "暂不支持该平台");
        }
        DewaterTypeEnum dewaterTypeEnum = DewaterTypeEnum.LIVE_DEWATER;
        Long userId = getSession().getUserId();
        if (userId == null || 0L == userId) {
            return BsResult.error(ResultCode.UN_LOGINED);
        }
        boolean isLimited = xhsBusinessManager.checkLimit(userId, dewaterTypeEnum);
        if (isLimited) {
            log.warn("小红书/抖音-live-去水印-用户当日超限-userId:{},内容:{}", userId, xhsDewaterDTO.getSource());
            return BsResult.error(ResultCode.FREE_LIMITED);
        }
        LiveImgVO result = null;
        //抖音链接 抖音-live去水印
        if (xhsDewaterDTO.getSource().contains(Constant.dyLinkPrefix)
                || xhsDewaterDTO.getSource().contains(Constant.dyLinkPrefix1)
                || xhsDewaterDTO.getSource().contains(Constant.dyLinkPrefix2)) {
            DouyinVO dyResult = douYinBusinessManager.handleLiveImages(xhsDewaterDTO.getSource());
            if (null == dyResult) {
                log.warn("红薯秀-抖音-live去水印-资源未找到:{}, source:{}", userId, xhsDewaterDTO.getSource());
                return BsResult.error(ResultCode.NOT_XHS_LIVE);
            }
            if (!dyResult.getRequestSuccess()) {
                log.warn("红薯秀-抖音-live去水印-接口异常:userId{}, source:{}", userId, xhsDewaterDTO.getSource());
                return BsResult.error(ResultCode.TRY_AGAIN);
            }
            result = new LiveImgVO();
            result.setRequestSuccess(dyResult.getRequestSuccess());
            //如果查询不到作品详情，通常是作品不存在或者下架了
            if (StringUtils.isNotBlank(dyResult.getShareUrl())) {
                result.setText(dyResult.getRemark());
                //获取Live实况图链接
                List<LiveImgVO.LiveImageInfo> liveImageList = new ArrayList<>();
                if (!CollectionUtils.isEmpty(dyResult.getLiveImages())) {
                    for (DouyinVO.LiveImageInfo dyliveInfo : dyResult.getLiveImages()) {
                        LiveImgVO.LiveImageInfo liveImageInfo = BeanUtil.copyProperties(dyliveInfo, LiveImgVO.LiveImageInfo.class);
                        liveImageList.add(liveImageInfo);
                    }
                } else if (!StringUtils.isBlank(dyResult.getVideoUrl())) {
                    LiveImgVO.LiveImageInfo liveImageInfo = new LiveImgVO().new LiveImageInfo();
                    liveImageInfo.setUrl(dyResult.getVideoUrl());
                    liveImageInfo.setCover(dyResult.getOriginCover());
                    liveImageList.add(liveImageInfo);
                }
                result.setLiveImages(liveImageList);
            }

        } else if (xhsDewaterDTO.getSource().contains(Constant.weiboLinkPrefix)
                || xhsDewaterDTO.getSource().contains(Constant.weiboLinkPrefix1)) {
            result = weiboBusinessManager.handleLiveImages(xhsDewaterDTO.getSource());
            if (result == null) {
                log.warn("红薯秀-微博-userId:{},无效内容0:{}", userId, xhsDewaterDTO.getSource());
                return BsResult.error(ResultCode.NOT_XHS_LIVE);
            }
            if (!result.getRequestSuccess()) {
                log.warn("红薯秀-微博-接口异常:userId{}, source:{}", userId, xhsDewaterDTO.getSource());
                return BsResult.error(ResultCode.TRY_AGAIN);
            }
        } else {
//        XhsLiveVO result = xhsBusinessManager.handleLiveImageFromAwemeDetail(xhsDewaterDTO.getSource());
            result = xhsBusinessManager.handleLiveImageMovVersion(xhsDewaterDTO.getSource());
        }
        if (result == null) {
            log.warn("小红书/抖音-live-去水印-userId:{},无效内容0:{}", userId, xhsDewaterDTO.getSource());
            return BsResult.error(ResultCode.NOT_XHS_LIVE);
        }
        if (!result.getRequestSuccess()) {
            log.warn("小红书/抖音-live-去水印-接口异常:userId{}, source:{}", userId, xhsDewaterDTO.getSource());
            return BsResult.error(ResultCode.TRY_AGAIN);
        }
        xhsDewaterRecordService.saveShowRecord(getClientRequest(getRequest()), userId, dewaterTypeEnum.getType(), xhsDewaterDTO.getSource(), JSON.toJSONString(result));
        //扣减次数
        xhsBusinessManager.reduceTime(userId, UserPrivilegeEnum.XHSLIVE, 1);
//        if (CollectionUtils.isEmpty(result.getVideoList())) {
//            return BsResult.error(ResultCode.NOT_XHS_LIVE);
//        }
        //如果查到了结果，但笔记中没有实况图，还是要记录的
        if (CollectionUtils.isEmpty(result.getLiveImages())) {
            log.warn("小红书/抖音-live-去水印-userId:{},source:{}没有实况图", userId, xhsDewaterDTO.getSource());
            return BsResult.error(ResultCode.NOT_XHS_LIVE);
        }
        return BsResult.success(result);
    }

    @PostMapping("/dewater")
    @ApiOperation(value = "去水印", notes = "去水印")
    @ResponseBody
    public BsResult parse(@RequestBody XhsDewaterDTO xhsDewaterDTO) {
        if (!Constant.checkeXhsDewaterSourceAccordWhiteUrl(xhsDewaterDTO.getSource())) {
            return BsResult.error(ResultCode.RESOURCE_NOT_VALID);
        }
        Long userId = getSession().getUserId();
        if (userId == null || 0L == userId) {
            return BsResult.error(ResultCode.UN_LOGINED);
        }
        DewaterTypeEnum dewaterTypeEnum = DewaterTypeEnum.DEWATER;
        boolean isLimited = xhsBusinessManager.checkLimit(userId, dewaterTypeEnum);
        if (isLimited) {
            log.warn("去水印-用户当日超限-userId:{},内容:{}", userId, xhsDewaterDTO.getSource());
            return BsResult.error(ResultCode.FREE_LIMITED);
        }
        if (!xhsDewaterDTO.getSource().contains("http")) {
            log.warn("去水印-userId:{},无效内容1:{}", userId, xhsDewaterDTO.getSource());
            return BsResult.error(ResultCode.RESOURCE_NOT_VALID);
        }
        VnilVO result = xhsBusinessManager.handleWater(xhsDewaterDTO.getSource(), false);
        if (result == null || !result.getRequestSuccess()) {
            log.warn("去水印-接口异常:userId{}, source:{}", userId, xhsDewaterDTO.getSource());
            return BsResult.error(ResultCode.TRY_AGAIN);
        }
        if (StringUtils.isBlank(result.getUrl())) {
            log.warn("去水印-userId:{},无效内容0:{}", userId, xhsDewaterDTO.getSource());
            return BsResult.error(ResultCode.RESOURCE_NOT_VALID);
        }
        xhsDewaterRecordService.saveShowRecord(getClientRequest(getRequest()), userId, dewaterTypeEnum.getType(), xhsDewaterDTO.getSource(), JSON.toJSONString(result));
        //扣减次数
        xhsBusinessManager.reduceTime(userId, UserPrivilegeEnum.XHSLIVE, 1);
        return BsResult.success(result);
    }

    @PostMapping("/dewater/animImg")
    @ApiOperation(value = "动图去水印-animImgParse", notes = "动图去水印-animImgParse")
    @ResponseBody
    public BsResult animImgParse(@RequestBody XhsDewaterDTO xhsDewaterDTO) {
        if (!Constant.checkeXhsDewaterSourceAccordWhiteUrl(xhsDewaterDTO.getSource())) {
            return BsResult.error(ResultCode.RESOURCE_NOT_VALID);
        }
        Long userId = getSession().getUserId();
        if (userId == null || 0L == userId) {
            return BsResult.error(ResultCode.UN_LOGINED);
        }
        DewaterTypeEnum dewaterTypeEnum = DewaterTypeEnum.ANIM_IMG_DEWATER;
        boolean isLimited = xhsBusinessManager.checkLimit(userId, dewaterTypeEnum);
        if (isLimited) {
            log.warn("动图去水印-用户当日超限-userId:{},内容:{}", userId, xhsDewaterDTO.getSource());
            return BsResult.error(ResultCode.FREE_LIMITED);
        }
        if (!xhsDewaterDTO.getSource().contains("http")) {
            log.warn("动图去水印-userId:{},无效内容1:{}", userId, xhsDewaterDTO.getSource());
            return BsResult.error(ResultCode.RESOURCE_NOT_VALID);
        }
        log.info("动图去水印-animImgParse-userId:{},videoUrl:{}", userId, xhsDewaterDTO.getSource());
        AnimImgVO result = null;
        if (xhsDewaterDTO.getSource().contains("http")) {
            result = xhsBusinessManager.handleAnimImage(xhsDewaterDTO.getSource(), false);
            if (result == null || !result.getRequestSuccess()) {
                log.warn("动图去水印-接口异常:userId{}, source:{}", userId, xhsDewaterDTO.getSource());
                return BsResult.error(ResultCode.TRY_AGAIN);
            }
            if (StringUtils.isBlank(result.getUrl())) {
                log.warn("动图去水印-userId:{},无效内容0:{}", userId, xhsDewaterDTO.getSource());
                return BsResult.error(ResultCode.RESOURCE_NOT_VALID);
            }
            xhsDewaterRecordService.saveShowRecord(getClientRequest(getRequest()), userId, dewaterTypeEnum.getType(), xhsDewaterDTO.getSource(), JSON.toJSONString(result));
            //扣减次数
            xhsBusinessManager.reduceTime(userId, UserPrivilegeEnum.XHSLIVE, 1);
            //如果查到了结果，但笔记中没有动图，还是要记录的
            if (CollectionUtils.isEmpty(result.getImages())) {
                log.warn("动图去水印-animImgParse-userId:{},source:{}没有动图", userId, xhsDewaterDTO.getSource());
                return BsResult.error(ResultCode.NOT_XHS_ANIM);
            }
        } else {
            log.warn("动图去水印-animImgParse-userId:{},无效内容1:{}", userId, xhsDewaterDTO.getSource());
            return BsResult.error(ResultCode.RESOURCE_NOT_VALID);
        }
        return BsResult.success(result);
    }


    /**
     * 从作品评论中提取评论、图片信息
     *
     * @return
     */
    @PostMapping("/dewater/commentInfo")
    @ApiOperation(value = "小红书-从作品评论中提取评论、图片信息-commentInfo")
    @ResponseBody
    public BsResult commentInfo(@RequestBody XhsDewaterDTO xhsDewaterDTO) {
        if (!Constant.checkeXhsDewaterSourceAccordWhiteUrl(xhsDewaterDTO.getSource())) {
            return BsResult.error(ResultCode.RESOURCE_NOT_VALID);
        }
        Long userId = getSession().getUserId();
        if (userId == null || 0L == userId) {
            return BsResult.error(ResultCode.UN_LOGINED);
        }
        DewaterTypeEnum dewaterTypeEnum = DewaterTypeEnum.COMMENT_INFO_DEWATER;
        boolean isLimited = xhsBusinessManager.checkLimit(userId, dewaterTypeEnum);
        if (isLimited) {
            log.warn("小红书-从作品评论中提取评论、图片信息-用户当日超限-userId:{},内容:{}", userId, xhsDewaterDTO.getSource());
            return BsResult.error(ResultCode.FREE_LIMITED);
        }
        if (!xhsDewaterDTO.getSource().contains("http")) {
            log.warn("小红书-从作品评论中提取评论、图片信息-userId:{},无效内容1:{}", userId, xhsDewaterDTO.getSource());
            return BsResult.error(ResultCode.RESOURCE_NOT_VALID);
        }
        log.info("小红书-从作品评论中提取评论、图片信息-userId:{},source:{}", userId, xhsDewaterDTO.getSource());
        try {
            VnilVO result = xhsBusinessManager.handleCommentInfoWater(xhsDewaterDTO.getSource(), false);
            if (result == null || !result.getRequestSuccess()) {
                log.warn("小红书-从作品评论中提取评论、图片信息-接口异常:userId{}, source:{}", userId, xhsDewaterDTO.getSource());
                return BsResult.error(ResultCode.TRY_AGAIN);
            }
            if (StringUtils.isBlank(result.getUrl())) {
                log.warn("小红书-从作品评论中提取评论、图片信息-userId:{},无效内容0:{}", userId, xhsDewaterDTO.getSource());
                return BsResult.error(ResultCode.RESOURCE_NOT_VALID);
            }
            xhsDewaterRecordService.saveShowRecord(getClientRequest(getRequest()), userId, dewaterTypeEnum.getType(), xhsDewaterDTO.getSource(), JSON.toJSONString(result));
            //扣减次数
            xhsBusinessManager.reduceTime(userId, UserPrivilegeEnum.XHSLIVE, 1);
            return BsResult.success(result);
        } catch (Exception ex) {
            log.error("红薯秀app-小红书-从笔记评论中提取评论、图片信息-异常:{}", ex);
            return BsResult.error(ResultCode.RESOURCE_NOT_FOUND);
        }
    }

    @PostMapping("/dewater/commentsLive")
    @ApiOperation(value = "小红书-评论区live-去水印", notes = "小红书-评论区live-去水印")
    @ResponseBody
    public BsResult commentsLive(@RequestBody XhsDewaterDTO xhsDewaterDTO) {
        if (StringUtils.isBlank(xhsDewaterDTO.getSource()) || !xhsDewaterDTO.getSource().contains("http")) {
            return BsResult.error(ResultCode.RESOURCE_NOT_VALID);
        }
        if (!Constant.checkeXhsSourceAccordWhiteUrl(xhsDewaterDTO.getSource())) {
            return BsResult.error(ResultCode.RESOURCE_NOT_VALID.getCode(), "非小红薯平台");
        }
        Long userId = getSession().getUserId();
        if (userId == null || 0L == userId) {
            return BsResult.error(ResultCode.UN_LOGINED);
        }
        DewaterTypeEnum dewaterTypeEnum = DewaterTypeEnum.COMMENTS_LIVE_DEWATER;
        boolean isLimited = xhsBusinessManager.checkLimit(userId, dewaterTypeEnum);
        if (isLimited) {
            log.warn("小红书-评论区live-去水印-用户当日超限-userId:{},内容:{}", userId, xhsDewaterDTO.getSource());
            return BsResult.error(ResultCode.FREE_LIMITED);
        }
        AwemeCommentLiveImgVO result = xhsBusinessManager.handleLiveImageFromXhsAwemeCommentLis(xhsDewaterDTO.getSource());
        if (result == null) {
            log.warn("小红书-评论区live-去水印-userId:{},无效内容0:{}", userId, xhsDewaterDTO.getSource());
            return BsResult.error(ResultCode.NOT_XHS_LIVE);
        }
        if (!result.getSuccess()) {
            log.warn("小红书-评论区live-去水印-接口异常:userId{}, source:{}", userId, xhsDewaterDTO.getSource());
            return BsResult.error(ResultCode.TRY_AGAIN);
        }
        xhsDewaterRecordService.saveShowRecord(getClientRequest(getRequest()), userId, dewaterTypeEnum.getType(), xhsDewaterDTO.getSource(), JSON.toJSONString(result));
        //扣减次数
        xhsBusinessManager.reduceTime(userId, UserPrivilegeEnum.XHSCOMMENTSLIVE, 1);
        return BsResult.success(result);
    }

    @PostMapping("/checkAwemeRank/getAwemeDetail")
    @ApiOperation(value = "小红书-笔记排名查询-获取作品详情", notes = "小红书-笔记排名查询-获取作品详情")
    @ResponseBody
    public BsResult checkAwemeRankAwemeDetail(@RequestBody XhsPortalParseDTO xhsPortalParseDTO) {
        if (xhsPortalParseDTO == null) {
            return BsResult.error(ResultCode.XH_LINK_INVALID);
        }
        xhsPortalParseDTO.setBusinessType(UserExpPackageTypeEnum.XHS_AWEME_RANK_QUERY.getCode());
        return checkAwemeIncludedAwemeDetail(xhsPortalParseDTO);
    }

    @PostMapping("/checkAwemeIncluded/getAwemeDetail")
    @ApiOperation(value = "小红书-笔记收录查询-获取作品详情", notes = "小红书-笔记收录查询-获取作品详情")
    @ResponseBody
    public BsResult checkAwemeIncludedAwemeDetail(@RequestBody XhsPortalParseDTO xhsPortalParseDTO) {
        Long start = System.currentTimeMillis();
        if (! Constant.checkeXhsSourceAccordWhiteUrl(xhsPortalParseDTO.getSource())) {
            return BsResult.error(ResultCode.XH_LINK_INVALID);
        }
        Long userId = getUserId();
        if (userId == null || 0L == userId) {
            return BsResult.error(ResultCode.UN_LOGINED);
        }
        TblUser user = getUser(userId);
        if (user == null) {
            return BsResult.error(ResultCode.UN_LOGINED);
        }
        //笔记排名次数校验
        if (xhsPortalParseDTO.getBusinessType() != null
                && xhsPortalParseDTO.getBusinessType() == UserExpPackageTypeEnum.XHS_AWEME_RANK_QUERY.getCode()) {
            TblUserExppackage userExppackage = userExppackageService.queryUserExppackage(user.getId(), UserExpPackageTypeEnum.XHS_AWEME_RANK_QUERY);
            if (userExppackage == null || userExppackage.getExpCount() == null || userExppackage.getExpCount() < 1) {
                return BsResult.error(ResultCode.FREE_LIMITED.getCode(), "笔记排名查询条数已不足，请联系客服购买次数");
            }
        }
        //笔记收录权限校验
        else {
            VipLevelEnum userVipLevel = VipLevelEnum.getByLevel(user.getVipLevelCode());
            Integer userPrivilegeTimes = null;
            //会员已经过期
            if (!VipLevelEnum.FREE.equals(userVipLevel)
                    && user.getVipEndTime().compareTo(new Date()) < 0) {
                userVipLevel = VipLevelEnum.FREE;
            }
            if (!VipLevelEnum.FREE.equals(userVipLevel)) {
                userPrivilegeTimes = xhsBusinessManager.getUserPrivilegeTimes(userId, UserPrivilegeEnum.XHS_AWEME_INCLUDED);
            }
            Integer isLimited = -1;
            if (null != userPrivilegeTimes && userPrivilegeTimes > 0) {
                isLimited = xhsBusinessManager.checkAwemeIncludedBaseInfoLimit(userId);
            }
            if (isLimited <= 0) {
                log.warn("小红书-笔记收录查询-用户当日超限-userId:{},内容:{}", userId, xhsPortalParseDTO.getSource());
                return getCheckAwemeIncludedLimitedError(userVipLevel);
            }
        }
        if (StringUtils.isBlank(xhsPortalParseDTO.getSource())
                || (!xhsPortalParseDTO.getSource().contains(Constant.xhsLinkPrefix0) && !xhsPortalParseDTO.getSource().contains(Constant.xhsLinkPrefix1))) {
            log.error("xhs-笔记收录查询-无效内容:userId{},source:{}", userId, xhsPortalParseDTO.getSource());
            return BsResult.error(ResultCode.XH_LINK_INVALID);
        }
        XhsAwemeLinkBaseInfo xhsAwemeLinkBaseInfo = xhsBusinessManager.getAwemeIdFromSource(xhsPortalParseDTO.getSource());
        if (xhsAwemeLinkBaseInfo == null || StringUtils.isBlank(xhsAwemeLinkBaseInfo.getAwemeId())) {
            log.warn("小红书-笔记收录查询-userId:{},无效内容0:{}", userId, xhsPortalParseDTO.getSource());
            return BsResult.error(ResultCode.XH_LINK_INVALID);
        }
        boolean awemeNormalDisplay = xhsBusinessManager.getAwemeNormalDisplay(xhsAwemeLinkBaseInfo.getAwemeId(), xhsAwemeLinkBaseInfo.getXSecToken());
        if (!awemeNormalDisplay) {
            log.warn("小红书-笔记收录查询-userId:{},无效内容-作品无法正常展示:{}", userId, xhsPortalParseDTO.getSource());
            return BsResult.error(ResultCode.XHS_AWEME_DELETE);
        }
        XhsAwemeDetail awemeInfo = xhsBusinessManager.getXhsAwemeDetail(xhsAwemeLinkBaseInfo.getAwemeId(), xhsAwemeLinkBaseInfo.getXSecToken());
        if (awemeInfo == null) {
            log.warn("小红书-笔记收录查询-userId:{},无效内容0:{}", userId, xhsPortalParseDTO.getSource());
            return BsResult.error(ResultCode.XH_LINK_INVALID);
        }
        if (awemeInfo.getNote() == null) {
            log.warn("红薯秀-笔记排名查询-获取作品详情-userId:{},接口异常:{}", userId, xhsPortalParseDTO.getSource());
            return BsResult.error(ResultCode.TRY_AGAIN);
        }
        //把笔记的封面图上传到oss，因为发现时间久了以后相关的图片会403，导致后续无法访问历史的笔记封面
        if (StringUtils.isNotBlank(awemeInfo.getCover())) {
            Environment environment = SpringContextUtil.getApplicationContext().getEnvironment();
            StringBuilder fullPath = new StringBuilder(Constant.xhsEditorDir).append("/")
                    .append(environment.getActiveProfiles()[0]).append("/")
                    .append(user.getId()).append("/")
                    .append(DateUtil.formatDate2yyyyMMdd(new Date())).append("/")
                    .append(UUID.randomUUID().toString().replaceAll("-",""))
                    .append(".jpg");
            String coverUrl = ossUtil.uploadFile2AliyunOss(awemeInfo.getCover(), fullPath.toString());
            awemeInfo.setCover(coverUrl);
        }
        //保存记录
        TblXhsAwemeDetailRecord record = new TblXhsAwemeDetailRecord();
        record.setUserId(userId);
        record.setSource(xhsPortalParseDTO.getSource());
        record.setAwemeId(xhsAwemeLinkBaseInfo.getAwemeId());
        record.setAwemeInfo(JSON.toJSONString(awemeInfo));
        record.setBusinessType(xhsPortalParseDTO.getBusinessType());
        Long traceId = xhsAwemeDetailRecordService.saveRecord(getClientRequest(), userId, record, System.currentTimeMillis() - start);
        if (traceId == null) {
            log.warn("xhs-笔记收录查询-接口异常:userId{}, result:{}", userId, awemeInfo);
            return BsResult.error(ResultCode.TRY_AGAIN);
        }
        XhsAwemeV2Resp resp = xhsBusinessManager.formatAwemeBaseInfo(awemeInfo);
        resp.setTraceId(traceId.toString());
        return BsResult.success(resp);
    }

    /**
     * 笔记收录查询-用户超限的提示
     *
     * @param userVipLevel
     * @return
     */
    private BsResult getCheckAwemeIncludedLimitedError(VipLevelEnum userVipLevel) {
        switch (userVipLevel) {
            case GE_1_MONTH:
            case GE_3_MONTH:
            case GE_6_MONTH:
            case GE_12_MONTH:
                return BsResult.error(ResultCode.FREE_LIMITED.getCode(), "笔记收录查询条数已不足(今天剩余查询条数0条，总查询200条/天)，请升级会员或联系客服购买次数");
            case FREE:
                return BsResult.error(ResultCode.FREE_LIMITED.getCode(), "笔记收录查询条数已不足(0条/天)，请升级会员");
            default:
                return BsResult.error(ResultCode.FREE_LIMITED.getCode(), "笔记收录查询条数已不足(今天剩余查询条数0条，总查询50条/天)，请升级会员或联系客服购买次数");
        }
    }

    @PostMapping("/checkAwemeRank")
    @ApiOperation(value = "小红书-笔记排名查询-checkAwemeRank")
    @ResponseBody
    public BsResult checkAwemeRank(@RequestBody XhsAwemeTaskDTO req) {
        if (req == null) {
            return BsResult.error(ResultCode.RESOURCE_NOT_VALID);
        }
        if (StringUtils.isBlank(req.getKeywords())) {
            return BsResult.error(ResultCode.NEED_KEYWORD);
        }
        req.setBusinessType(UserExpPackageTypeEnum.XHS_AWEME_RANK_QUERY.getCode());
        return checkAwemeIncluded(req);
    }

    @PostMapping("/checkAwemeIncluded")
    @ApiOperation(value = "小红书-笔记收录查询-checkAwemeIncluded")
    @ResponseBody
    public BsResult checkAwemeIncluded(@RequestBody XhsAwemeTaskDTO req) {
        Long start = System.currentTimeMillis();
        if (StringUtils.isBlank(req.getAwemeId()) || req.getAwemeDetailId() == null) {
            return BsResult.error(ResultCode.PARAM_VALID_ERROR);
        }
        //从入参中拆解出关键词
        List<String> keywordList = handleCheckAwemeRankKeyword(req.getKeywords());
        if (StringUtils.isNotBlank(req.getKeywords())) {
            //最多只能输入20个关键词
            if (keywordList.size() > 20) {
                return BsResult.error(ResultCode.PARAM_VALID_ERROR);
            }
            //对输入的关键词做一次安全校验
            String keywordStr = handleCheckAwemeRankKeyword2(req.getKeywords());
            ModerationRiskLevelEnum riskLevelEnum = editorAwemeBusinessManager.wxTextModeration(keywordStr);
            if(riskLevelEnum.getLevel() >= ModerationRiskLevelEnum.high.getLevel()){
                return BsResult.error(ResultCode.KEYWORD_VALID_NON_COMPLIANT);
            }
        }
        Long userId = getSession().getUserId();
        if (userId == null || 0L == userId) {
            return BsResult.error(ResultCode.UN_LOGINED);
        }
        TblUser user = getUser(userId);
        if (user == null) {
            return BsResult.error(ResultCode.UN_LOGINED);
        }
        VipLevelEnum userVipLevel = VipLevelEnum.getByLevel(user.getVipLevelCode());
        //笔记排名次数校验
        if (req.getBusinessType() != null
                && req.getBusinessType() == UserExpPackageTypeEnum.XHS_AWEME_RANK_QUERY.getCode()) {
            TblUserExppackage userExppackage = userExppackageService.queryUserExppackage(user.getId(), UserExpPackageTypeEnum.XHS_AWEME_RANK_QUERY);
            if (userExppackage == null || userExppackage.getExpCount() == null
                    || userExppackage.getExpCount() < keywordList.size()) {
                return BsResult.error(ResultCode.FREE_LIMITED.getCode(), "笔记排名查询条数已不足，请联系客服购买次数");
            }
        }
        //笔记收录权限校验
        else {
            req.setBusinessType(UserExpPackageTypeEnum.XHS_AWEME_INCLUDE_QUERY.getCode());
            Integer userPrivilegeTimes = null;
            //会员已经过期
            if (!VipLevelEnum.FREE.equals(userVipLevel)
                    && user.getVipEndTime().compareTo(new Date()) < 0) {
                userVipLevel = VipLevelEnum.FREE;
            }
            if (!VipLevelEnum.FREE.equals(userVipLevel)) {
                userPrivilegeTimes = xhsBusinessManager.getUserPrivilegeTimes(userId, UserPrivilegeEnum.XHS_AWEME_INCLUDED);
            }
            if (null == userPrivilegeTimes || userPrivilegeTimes <= 0) {
                log.warn("小红书-笔记收录查询-用户当日超限-userId:{},内容:{}", userId, req);
                return this.getCheckAwemeIncludedLimitedError(userVipLevel);
            }
        }
        //用前一步笔记详情查询的数据做一次参数的校验
        TblXhsAwemeDetailRecord awemeDetailRecord = xhsAwemeDetailRecordService.getById(req.getAwemeDetailId());
        if (awemeDetailRecord == null || !awemeDetailRecord.getUserId().equals(userId)) {
            return BsResult.error(ResultCode.REQ_REJECT);
        }
        XhsAwemeDetail awemeInfo = null;
        if (StringUtils.isNotBlank(awemeDetailRecord.getAwemeInfo())) {
            try {
                awemeInfo = JSON.parseObject(awemeDetailRecord.getAwemeInfo(), XhsAwemeDetail.class);
                //防止获取作品详情的小红书作品ID与用户传的小红书作品ID不一样。
                if (!req.getAwemeId().equals(awemeDetailRecord.getAwemeId())
                        && !req.getAwemeId().equals(awemeInfo.getAwemeId())
                ) {
                    return BsResult.error(ResultCode.PARAM_VALID_ERROR);
                }
                if (awemeInfo.getUser() == null || StringUtils.isBlank(awemeInfo.getUser().getUserid())) {
                    return BsResult.error(ResultCode.PARAM_VALID_ERROR);
                }
            } catch (Exception e) {
                return BsResult.error(ResultCode.PARAM_VALID_ERROR);
            }
        }
        if (awemeInfo == null) {
            return BsResult.error(ResultCode.PARAM_VALID_ERROR);
        }
        //任务id和关键词的映射关系，便于下面逐个发起任务的执行
        Map<Long, String> traceIdKeywordMap = new HashMap<>();
        //创建任务-笔记排名
        if (req.getId() == null && req.getBusinessType() != null
                && req.getBusinessType() == UserExpPackageTypeEnum.XHS_AWEME_RANK_QUERY.getCode()) {
            //先做资源次数扣减，这里核心是做一个冻结的动作
            boolean isok = userExppackageService.freezeUserAvailableTimes(user.getId(), UserExpPackageTypeEnum.XHS_AWEME_RANK_QUERY, keywordList.size());
            if (!isok) {
                return BsResult.error(ResultCode.FREE_LIMITED.getCode(), "笔记排名查询条数已不足，请联系客服购买次数");
            }
            for (String keyword : keywordList) {
                TblXhsCheckAwemeIncludedRecord record = new TblXhsCheckAwemeIncludedRecord();
                record.setUserId(userId);
                record.setAwemeDetailId(req.getAwemeDetailId());
                record.setAwemeId(req.getAwemeId());
                record.setAwemeInfo(JSON.toJSONString(awemeInfo));
                record.setBusinessType(req.getBusinessType());
                if (keyword.contains(":")) {
                    //这表示这个关键词信息里含有月均搜索指数，这是客户选择推荐关键词后，前端传过来的
                    record.setKeywordInfo(keyword);
                } else {
                    //这表示这个关键词信息里不含有月均搜索指数，这是客户自定义输入的关键词。这时候需要调用xhs商业的接口，获取该关键词的月均搜索指数
                    List<XhsSearchHotKeywordDTO> xhsSearchHotKeywordDTOList = shuXiuUtils.getXhsHotKeywords(keyword);
                    List<XhsSearchHotKeywordDTO> findIt = xhsSearchHotKeywordDTOList
                            .stream()
                            .filter(item -> item.getKeyword().equals(keyword))
                            .collect(Collectors.toList());
                    if (CollectionUtils.isEmpty(findIt)) {
                        record.setKeywordInfo(keyword + ":0");
                    } else {
                        record.setKeywordInfo(keyword + ":" + StringUtil.changeNumber2FuzzyWriting5(findIt.get(0).getMonthpv()));
                    }
                }
                Long traceId = xhsCheckAwemeIncludedRecordService.saveRecord(getClientRequest(), userId, record, System.currentTimeMillis() - start);
                traceIdKeywordMap.put(traceId, keyword);
            }
        }
        //创建任务-笔记收录
        else if (req.getId() == null) {
            //先做资源次数扣减
            boolean isok = xhsBusinessManager.reduceTime(userId, UserPrivilegeEnum.XHS_AWEME_INCLUDED, 1);
            if (!isok) {
                return this.getCheckAwemeIncludedLimitedError(userVipLevel);
            }
            TblXhsCheckAwemeIncludedRecord record = new TblXhsCheckAwemeIncludedRecord();
            record.setUserId(userId);
            record.setAwemeDetailId(req.getAwemeDetailId());
            record.setAwemeId(req.getAwemeId());
            record.setAwemeInfo(JSON.toJSONString(awemeInfo));
            record.setBusinessType(UserExpPackageTypeEnum.XHS_AWEME_INCLUDE_QUERY.getCode());
            Long traceId = xhsCheckAwemeIncludedRecordService.saveRecord(getClientRequest(), userId, record, System.currentTimeMillis() - start);
            traceIdKeywordMap.put(traceId, null);
        }
        //重试任务
        else {
            TblXhsCheckAwemeIncludedRecord record = xhsCheckAwemeIncludedRecordService.getById(req.getId());
            if (record == null || !record.getUserId().equals(userId)
                    || !record.getAwemeId().equals(req.getAwemeId())
                    || !record.getAwemeDetailId().equals(req.getAwemeDetailId())
            ) {
                return BsResult.error(ResultCode.PARAM_VALID_ERROR);
            }
            HistroyStatusEnum histroyStatusEnum = xhsBusinessManager.getCheckAwemeIncludedStatus(record.getIsLimited(), record.getIsIncluded(), record.getFinishTime(), record.getLastUpdate());
            if (!HistroyStatusEnum.Error.equals(histroyStatusEnum)) {
                return BsResult.error(ResultCode.PARAM_VALID_ERROR);
            }
            TblXhsCheckAwemeIncludedRecord upRecord = new TblXhsCheckAwemeIncludedRecord();
            upRecord.setId(record.getId());
            upRecord.setIsLimited(null);
            upRecord.setIsIncluded(null);
            upRecord.setRanking(null);
            upRecord.setAwemeCount(0);
            upRecord.setUserAwemeList("");
            upRecord.setSearchAwemeList("");
            upRecord.setSearchCriteria("");
            upRecord.setLastUpdate(new Date());
            xhsCheckAwemeIncludedRecordService.updateById(upRecord);
            traceIdKeywordMap.put(req.getId(), record.getKeywordInfo());
        }
        if (traceIdKeywordMap.size() == 0) {
            log.warn("xhs-笔记排名查询-接口异常:userId{}, result:{}", userId, awemeInfo);
            return BsResult.error(ResultCode.TRY_AGAIN);
        }
        //执行任务
        Set<Long> keySet = traceIdKeywordMap.keySet();
        for (Long traceId : keySet) {
            //拆解关键词的结构
            String finalKeyword = traceIdKeywordMap.get(traceId);
            if (StringUtils.isNotBlank(finalKeyword)) {
                finalKeyword = finalKeyword.split(":")[0];
            }
            checkAwemeIncludedAsyncService.executeAsyncCheckAwemeIncludedTask(traceId, awemeInfo, userId, finalKeyword, UserExpPackageTypeEnum.getByCode(req.getBusinessType()));
        }
        return BsResult.success(traceIdKeywordMap.size());
    }

    @GetMapping("/checkAwemeRank/histroy")
    @ApiOperation(value = "小红书-笔记收录查询-历史记录", notes = "小红书-笔记收录查询-历史记录")
    @ResponseBody
    public BsResult checkAwemeRankHistroy(@RequestParam(required = false) Integer page) {
        return this.checkAwemeIncludedHistroy(page, UserExpPackageTypeEnum.XHS_AWEME_RANK_QUERY.getCode());
    }

    @GetMapping("/checkAwemeIncluded/histroy")
    @ApiOperation(value = "小红书-笔记收录查询-历史记录", notes = "小红书-笔记收录查询-历史记录")
    @ResponseBody
    public BsResult checkAwemeIncludedHistroy(@RequestParam(required = false) Integer page, Integer businessType) {
        Long userId = getSession().getUserId();
        if (userId == null || 0L == userId) {
            return BsResult.error(ResultCode.UN_LOGINED);
        }
        if (businessType == null) {
            businessType = UserExpPackageTypeEnum.XHS_AWEME_INCLUDE_QUERY.getCode();
        }
        log.info("小红书-笔记收录查询-历史记录-userId:{}", userId);
        Integer count = xhsCheckAwemeIncludedRecordService.queryCount(userId, businessType);
        if (count.intValue() == 0) {
            return BsResult.error(ResultCode.RESOURCE_NOT_FOUND);
        }
        List<TblXhsCheckAwemeIncludedRecord> recordList = xhsCheckAwemeIncludedRecordService.queryPageList(userId, businessType, page == null ? 1 : page, 10);
        if (recordList == null) {
            return BsResult.error(ResultCode.RESOURCE_NOT_FOUND);
        }
        List<CheckAwemeIncludedListResp> respList= new ArrayList<>();
        recordList.forEach(record->{
            CheckAwemeIncludedListResp resp=new CheckAwemeIncludedListResp();
            resp.setCount(count);
            resp.setId(record.getId());
            resp.setAwemeInfo(record.getAwemeInfo());
            resp.setCreateTime(record.getCreateTime());
            resp.setFinishTime(record.getFinishTime());
            resp.setKeywordInfo(record.getKeywordInfo());
            HistroyStatusEnum histroyStatusEnum = xhsBusinessManager.getCheckAwemeIncludedStatus(record.getIsLimited(), record.getIsIncluded(), record.getFinishTime(), record.getLastUpdate());
            resp.setState(histroyStatusEnum.getCode());
            switch (histroyStatusEnum) {
                case Not_Started:
                case Running:
                    resp.setFinishTime(null);
                    break;
                case Complete:
                    XhsAwemeIsLimitedEnum xhsAwemeIsLimitedEnum = XhsAwemeIsLimitedEnum.getByCode(record.getIsLimited());
                    XhsAwemeBusinessV2 xhsAwemeBusinessV2 = new XhsAwemeBusinessV2();
                    if (StringUtils.isNotBlank(record.getSearchCriteria())) {
                        xhsAwemeBusinessV2.setSearchCriteria(JSON.parseObject(record.getSearchCriteria(), SearchCriteriaDTO.class));
                    }
                    xhsAwemeBusinessV2.setIncluded(XhsAwemeIsIncludedEnum.getByCode(record.getIsIncluded()));
                    xhsAwemeBusinessV2.setRanking(record.getRanking());
                    xhsAwemeBusinessV2.setAwemeCount(record.getAwemeCount());
                    XhsAwemeIncludedDTO xhsAwemeIncludedDTO = xhsBusinessManager.checkAwemeIncludedResult(xhsAwemeIsLimitedEnum, xhsAwemeBusinessV2);
                    resp.setIsIncluded(xhsAwemeIncludedDTO.getIsIncluded());
                    resp.setRank(record.getRanking() == null ? ">100" : record.getRanking().toString());
                    resp.setSearchCriteria(xhsAwemeIncludedDTO.getSearchCriteria());
                    break;
            }
            respList.add(resp);
        });
        return BsResult.success(respList);
    }

    @PostMapping("/checkAwemeIncluded/delete")
    @ApiOperation(value = "小红书-笔记收录查询-删除收录结果-checkAwemeIncludedDelete")
    @ResponseBody
    public BsResult checkAwemeIncludedDelete(@RequestBody XhsAwemeTaskDTO req) {
        Long start = System.currentTimeMillis();
        if (req.getId() == null) {
            return BsResult.error(ResultCode.PARAM_VALID_ERROR);
        }
        Long userId = getSession().getUserId();
        if (userId == null || 0L == userId) {
            return BsResult.error(ResultCode.UN_LOGINED);
        }
        TblXhsCheckAwemeIncludedRecord record = xhsCheckAwemeIncludedRecordService.getById(req.getId());
        if (record == null || !record.getUserId().equals(userId)) {
            return BsResult.error(ResultCode.PARAM_VALID_ERROR);
        }
        HistroyStatusEnum histroyStatusEnum = xhsBusinessManager.getCheckAwemeIncludedStatus(record.getIsLimited(), record.getIsIncluded(), record.getFinishTime(), record.getLastUpdate());
        if (!HistroyStatusEnum.Complete.equals(histroyStatusEnum)) {
            return BsResult.error(ResultCode.ONLY_COMPLETE_TASK_CAN_BE_DELETED);
        }
        boolean isok = xhsCheckAwemeIncludedRecordService.removeById(record.getId());
        if (isok) {
            return BsResult.success("删除成功");
        } else {
            return BsResult.error("删除失败");
        }
    }

    @PostMapping("/checkAwemeRank/recommend/keywords")
    @ApiOperation(value = "小红书-笔记排名查询-获取笔记的推荐关键词")
    @ResponseBody
    public BsResult checkAwemeRankRecommendKeywords(@RequestBody XhsAwemeTaskDTO req) {
        if (StringUtils.isBlank(req.getAwemeId()) || req.getAwemeDetailId() == null) {
            return BsResult.error(ResultCode.PARAM_VALID_ERROR);
        }
        Long userId = getSession().getUserId();
        if (userId == null || 0L == userId) {
            return BsResult.error(ResultCode.UN_LOGINED);
        }
        TblUser user = getUser(userId);
        if (user == null) {
            return BsResult.error(ResultCode.UN_LOGINED);
        }
        //笔记排名次数校验
        TblUserExppackage userExppackage = userExppackageService.queryUserExppackage(user.getId(), UserExpPackageTypeEnum.XHS_AWEME_RANK_QUERY);
        if (userExppackage == null || userExppackage.getExpCount() == null || userExppackage.getExpCount() < 1) {
            return BsResult.error(ResultCode.FREE_LIMITED.getCode(), "笔记排名查询条数已不足，请联系客服购买次数");
        }
        TblXhsAwemeDetailRecord awemeDetailRecord = xhsAwemeDetailRecordService.getById(req.getAwemeDetailId());
        if (awemeDetailRecord == null || !awemeDetailRecord.getUserId().equals(userId)) {
            return BsResult.error(ResultCode.REQ_REJECT);
        }
        XhsAwemeDetail awemeInfo = null;
        if (StringUtils.isNotBlank(awemeDetailRecord.getAwemeInfo())) {
            try {
                awemeInfo = JSON.parseObject(awemeDetailRecord.getAwemeInfo(), XhsAwemeDetail.class);
                //防止获取作品详情的小红书作品ID与用户传的小红书作品ID不一样。
                if (!req.getAwemeId().equals(awemeDetailRecord.getAwemeId())
                        && !req.getAwemeId().equals(awemeInfo.getAwemeId())
                ) {
                    return BsResult.error(ResultCode.PARAM_VALID_ERROR);
                }
                if (awemeInfo.getUser() == null || StringUtils.isBlank(awemeInfo.getUser().getUserid())) {
                    return BsResult.error(ResultCode.PARAM_VALID_ERROR);
                }
            } catch (Exception e) {
                return BsResult.error(ResultCode.PARAM_VALID_ERROR);
            }
        }
        if (awemeInfo == null) {
            return BsResult.error(ResultCode.PARAM_VALID_ERROR);
        }
        List<XhsSearchHotKeywordDTO> xhsSearchHotKeywordDTOList = shuXiuUtils.getXhsAwemeRecommondKeywords(req.getAwemeId());
        List<XhsSearchHotKeywordVO> result = new ArrayList<>();
        if (! CollectionUtils.isEmpty(xhsSearchHotKeywordDTOList)) {
            // 按 monthpv 倒序排序
            xhsSearchHotKeywordDTOList.sort((o1, o2) -> o2.getMonthpv().compareTo(o1.getMonthpv()));
            result = xhsSearchHotKeywordDTOList.stream().map(xhsSearchHotKeywordDTO -> {
                XhsSearchHotKeywordVO xhsSearchHotKeywordVO = new XhsSearchHotKeywordVO();
                xhsSearchHotKeywordVO.setKeyword(xhsSearchHotKeywordDTO.getKeyword());
                xhsSearchHotKeywordVO.setMonthpv(StringUtil.changeNumber2FuzzyWriting5(xhsSearchHotKeywordDTO.getMonthpv()));
                return xhsSearchHotKeywordVO;
            }).collect(Collectors.toList());
        }
        return BsResult.success(result);
    }

    /**
     * 笔记排名查询，把用户传过来的关键词转成list
     * @param originalKeywords
     * @return
     */
    private List<String> handleCheckAwemeRankKeyword(String originalKeywords) {
        if (StringUtils.isBlank(originalKeywords)) {
            return null;
        }
        String[] keywordStr = originalKeywords.split(",");
        List<String> keywordList = new ArrayList<>();
        for (String keyword : keywordStr) {
            if (StringUtils.isBlank(keyword)) {
                continue;
            }
            keywordList.add(keyword);
        }
        return keywordList;
    }

    /**
     * 笔记排名查询，把用户传过来的关键词转成字符串，不同的字符串用逗号隔开，并且去掉pv数据
     * @param originalKeywords
     * @return
     */
    private String handleCheckAwemeRankKeyword2(String originalKeywords) {
        if (StringUtils.isBlank(originalKeywords)) {
            return null;
        }
        String[] keywordStr = originalKeywords.split(",");
        StringBuilder result = new StringBuilder("");
        for (String keyword : keywordStr) {
            if (StringUtils.isBlank(keyword)) {
                continue;
            }
            result.append(keyword.split(":")[0]).append(",");
        }
        return result.substring(0, result.lastIndexOf(","));
    }
}
